\chapter{Nuestra Propuesta} % (fold)
\label{cha:propuesta}

% \begin{figure}[ht]
%  \centering
%  \includegraphics[width=0.6\textwidth]{images/monito}
% \end{figure}

En este capítulo se revisan las consideraciones de diseño que guiaron la
solución que proponemos. 

Muchas organizaciones disponen de una infraestructura moderna de
telecomunicaciones y cómputo que, sin embargo, se encuentra subutilizada. De
poder coordinarse con eficiencia, esta misma infraestructura les permitiría
disponer de una capacidad de almacenamiento en el orden de los
terabytes\index{terabytes} o incluso petabytes\index{petabytes}, sin caer en
costos agregados, al mismo tiempo que podrán mejorar varios de sus procesos.
Para aprovechar estos recursos y gestionar su crecimiento hay que comenzar
reconociendo la heterogeneidad de los componentes que participarían en un
proyecto de tales características: diferentes marcas, modelos, sistemas
operativos, capacidades, patrones de utilización, contenidos y, en muchos
casos, hay que considerar que no existe y no se juzga pertinente introducir  la
figura de una entidad central coordinadora. Se busca entonces, construir un
sistema distribuido, auto-organizado\index{auto-organizado}, en donde los
participantes puedan asumir roles cooperativos y simétricos, es decir, que al
mismo tiempo puedan ofrecer y recibir recursos hacia y desde el colectivo en el
que se integran, minimizando en lo posible las dependencias sobre puntos que
concentren algún tipo de actividad. 

\section{Consideraciones de diseño\index{diseño, Consideraciones de}} % (fold)
\label{sec:consideraciones}

Luego de revisar los trabajos destacados en el área, pudimos reconocer los
aspectos más importantes que deben tomarse en cuenta al momento de proponer la
arquitectura\index{arquitectura} para un nuevo sistema de almacenamiento
distribuido\index{sistema de almacenamiento distribuido}. La tabla
\ref{tbl:aspectos} condensa los elementos de diseño  que se repiten  en las
referencias consultadas.

\begin{center}
\begin{table}
 \scriptsize
 \begin{center}
  \rowcolors{2}{LightGray}{White}
  \begin{tabular}{ p{3in} c  c  c  c  c }
   \textbf{Aspecto} & \textbf{Harren\index{Harren}} & \textbf{Sung\index{Sung}} &
   \textbf{Hasan\index{Hasan}} & \textbf{CEPH\index{CEPH}} & \textbf{GFS\index{GFS}}\\
   \toprule
   Administración dinámica y
   distribuida de metadatos\index{metadatos}      & & & & \checkmark &            \\ 
   % Almacenar información         & \checkmark & & & & \checkmark \\ 
   Balance de carga\index{balance de carga}              & & & \checkmark & & \checkmark \\ 
   Consultas via DHT\index{DHT}             & \checkmark & & & &            \\ 
   Control de acceso             & & \checkmark & & &            \\ 
   Escalabilidad\index{escalabilidad}                 & & & \checkmark & & \checkmark \\ 
   Espacios autónomos y                               
   confiables de almacenamiento  & & & & \checkmark & \checkmark \\ 
   Identificar información       & & \checkmark & & &            \\ 
   Localización de recursos\index{localización de recursos}      & & & \checkmark & &  \\ 
   Persistencia\index{persistencia}                  & & & \checkmark & & \\ 
   Preservar la consistencia\index{consistencia}     & & \checkmark & & & \\ 
   Seguridad\index{seguridad}                     & & & \checkmark & & \\ 
   Separación datos\index{datos} - metadatos. & & & & \checkmark & \checkmark \\ 
   Simetría\index{simetría}                      & & & \checkmark & & \\ 
   \toprule

  \end{tabular}
 \end{center}
 \normalsize
 \caption{Aspectos a Considerar en el Diseño de un SAD\index{SAD}}
 \label{tbl:aspectos}
\end{table}
\end{center}

Como hemos adelantado, el diseño de un Sistema de Almacenamiento Distribuido
requiere:

\begin{enumerate}
 \item El conjunto de requisitos funcionales\index{requisitos funcionales} y no
  funcionales que se busca atender.
  
 \item Los parámetros de desempeño\index{parámetros de desempeño} que
  garanticen la calidad de servicio.

 \item La entidad o espacio elemental de almacenamiento\index{almacenamiento}.
\end{enumerate}

Los requerimientos funcionales\index{requerimientos funcionales} se refieren a
las necesidades del usuario o cliente final del sistema. En tanto, los
requerimientos no funcionales\index{requerimientos no funcionales} se refieren
a los atributos de calidad que tienen que satisfacerse para que el sistema
funcione adecuadamente.
% @TODO No me gusta la definición de requerimientos no funcionales.
 
Los parámetros de desempeño\index{parámetros de desempeño} de un SAD\index{SAD}
evalúan la eficiencia en el uso de los recursos implicados en la solución de
almacenamiento, así como la calidad de servicio\index{calidad de servicio} que
se ofrece.
 
Por cuanto se refiere a la entidad elemental de almacenamiento, de primera
instancia podría pensarse en los discos asociados con las computadoras
participantes en un SAD\index{SAD}.  Sin embargo, en vista de la escala a la
que se puede crecer y la complejidad de las operaciones que pueden tener lugar,
se considera contraproducente asumir una dependencia tan fuerte sobre
dispositivos individuales. Es deseable construir un dispositivo
virtual\index{dispositivo virtual} que exhiba una vida útil más prolongada y un
comportamiento más estable que lo que puede esperarse de los dispositivos
físicos a partir de los cuales se construya.  

% section consideraciones (end)

\section{Requerimientos funcionales\index{requerimientos funcionales}} % (fold)
\label{sec:reqf}

El diseño de un SAD\index{SAD} incluye la formalización de los procesos de
tratamiento de la información y los aspectos arquitectónicos que gobiernan su
construcción.  A partir de estos se identifican los requerimientos funcionales
\index{requerimientos funcionales} y no funcionales del sistema, respectivamente.  

Los requerimientos funcionales definen el comportamiento interno del software:
cálculos, detalles técnicos, manipulación de datos y otras funcionalidades
específicas que muestran cómo los casos de uso serán llevados a la práctica. 
Son complementados por los requerimientos no funcionales\index{requerimientos
no funcionales}, que se enfocan en el diseño o la implementación
\cite{sommerville}. En este sentido, los primeros responden a la pregunta ¿qué
se necesita?, mientras que los segundos guian el diseño de la arquitectura al
describir cualidades que debe tener el producto final.
% responden a la pregunta ¿cómo se resuelven las necesidades?

\begin{description}

 \item[Monitoreo\index{monitoreo} y control\index{control}]

 Se requiere una entidad del sistema capaz de llevar un control de los
 componentes en operación, verificar los parámetros de desempeño del sistema
 (balance de carga, redundancia\index{redundancia}, disponibilidad) e invocar a
 los mecanismos de regulación o reparación~\cite{deswarte}, por ejemplo, cuando
 haya que migrar contenidos de un disco viejo a un disco nuevo, o cuando el
 sistema se desvíe de sus especificaciones.

 \textit{Con el fin de atender este requerimiento, el prototipo
 \index{prototipo}es capaz de registrar todos los eventos\index{eventos} que
 suceden en él mediante el uso de bitácoras\index{bitácoras}, empleando estas
 bitácoras el sistema será capaz de detectar fallas, y en consecuencia lanzar
 el procedimiento co\-rres\-pon\-dien\-te para recuperarse de la misma.}
 % @TODO Mas detalle pendiente

 \item[Metadatos\index{metadatos}]

  Los metadatos\index{metadatos} son la información a partir de la cual se
  gestiona la aplicación.  Son los datos relacionados con los usuarios, sus
  cuotas, los atributos de acceso\index{atributos de acceso} a los recursos
  almacenados, la localización física de los archivos, tamaño, relaciones,
  etcétera. En breve, se trata de una base de datos\index{base de
  datos}. Sin embargo, su diseño incluye decisiones vinculadas no solo con su
  contenido y operaciones, sino con su localización\index{localización}. Una
  base de datos centralizada ofrece una administración muy sencilla, pero puede
  convertirse en un cuello de botella\index{cuello de botella} que limita la
  calidad de servicio\index{calidad de servicio}. En contraste, una base de
  datos distribuida puede ofrecer un alto desempeño pero, a cambio, se
  requieren mecanismos de acceso sincronizado y control de información
  replicada.

  \textit{Los metadatos del prototipo\index{prototipo} son
  almacenados en una base de datos relacional. El manejador de base de datos
  elegido es PostgreSQL\index{PostgreSQL}. La estructura de estos metadatos es
  definida en capítulo~\ref{cha:prototipo}.}
 % poner en qué seccion detallo las cosas para todos

 \item[Consistencia y sincronización]

 En un SAD\index{SAD} se necesita definir una política para sincronizar el
 manejo concurrente de contenidos\index{manejo concurrente de contenidos}, esto
 quiere decir que  se debe definir de qué forma se soportan las solicitudes
 simultáneas de acceso a un mismo recurso. Se pueden soportar, por ejemplo,
 varias lecturas simultaneas y una sola escritura. 

 Existen archivos, tanto de los usuarios como del propio sistema, que pueden
 encontrarse replicados en varios sitios. En estas circunstancias, una
 operación de escritura que modifique una réplica deberá repercutirse con el
 fin de garantizar la consistencia\index{consistencia} del conjunto de copias.
 Luego de este aseguramiento, cualquier entidad tendría acceso a la misma
 información, independientemente de la copia que recibiera. Sin embargo, existe
 una ventana de tiempo durante la cual el sistema cuenta con al menos dos
 versiones del mismo archivo. En este lapso, la falla\index{falla} de algún
 componente involucrado pondría en riesgo el éxito de la operación. Las
 especificaciones del sistema deben considerar, por tanto, la clase de fallas
 que pueden tolerarse y los protocolos con los que se les haría frente, llegado
 el caso. 

 \textit{En el prototipo se optó por un mecanismo muy sencillo para preservar
 la consistencia, el cual consiste en establecer que todos los objetos
 almacenados son inmutables\index{inmutables}, con lo que evitamos la necesidad
 de introducir un mecanismo de sincronización al momento de realizar
 operaciones de lectura\index{lectura}; en cuanto a la operación de
 escritura\index{escritura}, el mecanismo a seguir es el siguiente: Cada vez
 que un usuario quiere ``editar'' un objeto previamente almacenado en el
 sistema, lo que realmente sucede es que el objeto modificado se almacena como
 un archivo nuevo, que corresponde a la siguiente versión\index{versión} del
 archivo original, a partir de ese momento, todas las consultas de ese objeto
 obtendrán como resultado la nueva versión del archivo.}

 \item[Integridad y confidencialidad]

 La información se expone a un medio con limitaciones físicas por el que debe
 viajar o almacenarse. Este medio representa una fuente de errores que pueden
 modificar los dígitos binarios que componen un archivo. Preservar la
 integridad \index{integridad} es garantizar que el contenido que el usuario
 recupera del sistema de almacenamiento corresponde al contenido que almacenó
 en él originalmente, aún en presencia de factores que pueden degradar el
 servicio de almacenamiento. Por otro lado, la confidencialidad
 \index{confidencialidad} se refiere a la garantía para acceder a un archivo y
 su contenido, solo en los casos que el usuario que lo solicita tiene derechos
 sobre el mismo.

 Una característica común de los SAD\index{SAD} es el uso de la
 redundancia\index{redundancia} de información\index{información} para proveer
 tolerancia a fallas\index{tolerancia a fallas} y, en particular,
 integridad\index{integridad}. La estrategia más sencilla consiste en la
 replicación de archivos\index{replicación de archivos}. Esta técnica se
 utiliza por ejemplo en PAST\index{PAST}~\cite{rowstron} y
 Farsite\index{Farsite}~\cite{adya}. En estos sistemas, los componentes de
 almacenamiento participan con sus capacidades individuales para guardar
 réplicas de cada archivo en custodia. En contraste, existen sistemas como
 OceanStore\index{OceanStore}~\cite{kubiatowicz} o
 Intermemory\index{Intermemory}~\cite{chen}, en los que la
 redundancia\index{redundancia} se implementa mediante técnicas de detección y
 correción de errores, por ejemplo usando códigos de la familia
 Reed-Solomon\index{Reed-Solomon}, códigos de red\index{códigos de red},
 fuentes digitales\index{fuentes digitales}, entre otros. En estos casos, cada
 archivo se transforma en un conjunto de bloques codificados\index{bloques
 codificados} que luego son alojados en los componentes de almacenamiento
 disponibles.

 La selección de una estrategia en particular tiene un fuerte impacto en
 aspectos operacionales tales como el costo y la administración. Estudios
 recientes~\cite{rodrigues} sugieren que cuando los dispositivos exhiben un
 comportamiento estable de largo plazo, el sistema puede sacar provecho de una
 estrategia conservadora\index{estrategia conservadora} basada en códigos. En
 tanto, si los dispositivos tienen un comportamiento intermitente, el sistema
 debe basarse en una estrategia más agresiva, usando replicación. También se
 sabe de estrategias mixtas\index{estrategias mixtas} que combinan lo mejor de
 cada opción.

 Por cuanto se refiere a la confidencialidad\index{confidencialidad}, se trata
 de dar solución a un requerimiento de diseño teniendo en cuenta qué tanto los
 usuarios, como el propio sistema pueden almacenar información sensible y deben
 disponer de esta garantía. La información puede quedar expuesta al uso no
 autorizado ya sea durante su transmisión, o bien, durante su almacenamiento.
 En ambos casos se deben tomar las previsiones que limiten el riesgo. Sin
 embargo, la confidencialidad\index{confidencialidad} de la información no solo
 depende de su aseguramiento criptográfico, se deben considerar los mecanismos
 que limitan el acceso a la información dependiendo del rol\index{rol} que cada
 usuario tiene asignado en una organización.  

 \textit{La satisfacción de la integridad se logra en el prototipo, aplicando
 el algoritmo MD5 a los contenidos que son almacenados, con la finalidad de
 verificar que los datos no se hayan corrompido, y en caso de que esto ocurra,
 detectar en qué momento del proceso de almacenamiento o recuperación, ocurrió
 la pérdida de datos,
 %gracias al uso de técnicas de generación de redundancia\index{redundancia,
 %generación de}, ya sea replicando la información, o codificándola,
 en tanto que la confidencialidad se atiende por medio del manejo de cuentas y
 grupos de usuarios que le permiten al sistema otorgar o denegar el acceso a
 los objetos almacenados, en función de los privilegios asociados con su cuenta. }
 % @TODO falta hablar de la confidencialidad

 \item[Indexación y búsqueda\index{búsqueda}]

 Cada uno de los dispositivos de almacenamiento\index{dispositivos de
 almacenamiento} que participan debe contar con un identificador único que lo
 distinga del resto. Esta decisión dota al conjunto de una estructura a través
 de la cual es posible definir la posición donde se guarda un archivo, pero
 también define la manera de acceder al dispositivo que corresponde. Los
 mecanismos tradicionales encontrados en los sistemas de archivos no parecen
 adaptarse bien al manejo de volúmenes masivos.  En estos casos se requieren
 mecanismos ágiles y distribuidos para emplazar y localizar contenidos. En los
 sistemas P2P\index{P2P}, por ejemplo, se observa que los algoritmos basados en
 tablas de dispersión distribuida (DHT\index{DHT}\footnote{\textit{Distributed
 Hash Table} por sus siglas en inglés}) recuperan información basándose en un
 identificador único~\cite{balakrishnan}.  Se proporciona el nombre del archivo
 que se busca y la función de dispersión\index{función de dispersión} lo
 relaciona con la posición o identificador del dispositivo en el que se guarda.
 Sin embargo, para efectuar las consultas más elaboradas no basta proporcionar
 el nombre de un archivo, en muchos casos se requieren consultas semánticas,
 que se refieren a conceptos o palabras clave que describen el contenido de un
 grupo de documentos.

 \textit{La indexación\index{indexación} y búsqueda de información, queda 
 ``resuelta'' a nivel del prototipo haciendo uso de los metadatos; sin embargo
 no se contempló en esta versión del sistema el uso de un índice distribuido
 (aunque está considerado en la arquitectura\index{arquitectura}) debido a que
 no se necesita para esta etapa del proyecto.}

 \item[Interfaz de aplicación]

 Los usuarios de un SAD\index{SAD} podrán dar de alta y baja sus equipos,
 conectarse, desconectarse, almacenar archivos, borrarlos y recuperar
 contenidos usando diferentes criterios de búsqueda. Por otro lado, cada
 máquina deberá interactuar con un conjunto heterogéneo de componentes
 incluyendo programas escritos en diferentes lenguajes, diferentes sistemas
 operativos, diferentes capacidades de procesamiento y almacenamiento, entre
 varias posibilidades. Por lo anterior, es muy importante garantizar que la
 interfaz de aplicación\index{interfaz de aplicación} facilite la
 interoperabilidad\index{interoperabilidad}.  Igualmente es importante que la
 instalación de las diferentes versiones del SAD\index{SAD} tengan un impacto
 mínimo en las máquinas de los usuarios finales.  Desde esta perspectiva, los
 usuarios deberían considerarse como clientes de un servicio. Como en el caso
 de los abonados del sistema telefónico, a quienes se les instala un equipo
 cuando se suscriben y para ellos resultan transparentes las actualizaciones
 posteriores o cambios en el sistema que les da soporte.  

 \textit{Este requerimiento puede satisfacerse dotando al prototipo de una
 interfaz que le sirva para conectarse con otros sistemas y así poder brindar
 servicios de almacenamiento separando lo más posible la interfaz de
 aplicación\index{interfaz de aplicación} del núcleo del sistema, y que la
 conexión entre ellos se realice a través de un API \index{API}.}
 % @TODO completar este

\end{description}

\section{Requerimientos no funcionales}
\label{sec:reqnf}

Los requerimientos no funcionales\index{requerimientos no funcionales} se
refieren a los aspectos de diseño que gobiernan la arquitectura de las
soluciones. A partir de ellos se establecen criterios y prioridades que se
busca atender en el proceso de desarrollo del software. 

\begin{description}

 \item[Flexibilidad]

 Aún faltan estudios concluyentes que definan la mejor manera de resolver o
 proveer cada una de las funciones que se requieren en un SAD\index{SAD}. Por
 otro lado, parece razonable pensar que un sistema de este tipo pueda
 evolucionar y encontrar nuevas maneras de proveer las funciones que ya tiene
 implantadas.  Por lo anterior, un diseño estratégico pasaría por definir estas
 funciones como módulos\index{módulos} o cajas negras con entradas y salidas
 bien establecidas, dejando la posibilidad de variar su construcción, en tanto
 las interfaces permanezcan sin cambios.

 \textit{Por un lado, siguiendo una de las ideas propuestas en~\cite{sung} los
 componentes del sistema, pueden estar presentes o no (en el caso del prototipo,
 pueden estar activos o no), dependiendo de las tareas que van a desempeñar en
 el sistema, lo que significa que los módulos de la arquitectura
 \index{arquitectura} están debilmente acoplados entre sí. Por otro lado, es
 muy sencillo agregar funcionalidad al prototipo debido a su diseño, dado que
 los componentes del sistema pueden verse como cajas negras, con una interfaz
 bien definida que brinda la posibilidad de socializar el desarrollo del
 proyecto repartiendo la responsabilidad de implementar los componentes por
 separado y finalmente integrarlos para construir el producto final.}

 \item[Interoperabilidad]

 La posibilidad de intercambiar información proveniente de distintas fuentes,
 sugiere que ésta puede registrarse de acuerdo con formatos diferentes. Ya se
 ha mencionado que se trata de una tendencia que cobrará mayor relevancia con
 el tiempo. Dependiendo del nivel operativo en el que se aborde el problema,
 habrá aspectos particulares implicados en la solución. En todo caso, la
 interoperabilidad\index{interoperabilidad} será posible siempre que  se
 definan mecanismos estandarizados para invocar o proveer servicios entre las
 entidades involucradas. Se trata de un principio de diseño que complementa a
 la modularidad y que cobra mayor relevancia en la misma medida en que crece la
 heterogeneidad de los componentes que buscan coordinarse.

 \textit{Dado el diseño de la interfaz de usuario\index{interfaz de usuario} y
 comunicaciones \index{comunicaciones}, el prototipo puede adaptarse facilmente
 para interactuar con otros sistemas, este aspecto se explicará más a detalle
 en la sección~\ref{sec:almacen}.} % @TODO Revisar la redacción.

 \item[Escalabilidad]

 Se refiere a la manera en que se planea el crecimiento del sistema. Se
 entiende que al aumentar el número de componentes de almacenamiento crece la
 capacidad del sistema, pero igualmente pueden crecer los conflictos por el uso
 compartido de recursos, comenzando por la designación de los sitios de
 almacenamiento, los mecanismos para el emplazamiento\index{emplazamiento} y
 localización\index{localización} de la información, las políticas de acceso,
 entre muchos aspectos que deben considerarse. Visto de otra forma, el problema
 puede plantearse como una pregunta, ¿cómo pasar de un sistema basado en una
 red local, a un sistema del tamaño de la Internet, de modo que no se degraden
 sus prestaciones mientras crece? Desde esta perspectiva, la
 escalabilidad\index{escalabilidad} se puede entender como un principio de
 diseño que permite que los sistemas evolucionen de lo sencillo a lo complejo.

 \textit{La interacción con el sistema se hará a través de una interfaz que le
 permitirá agregar más nodos para aprovechar sus recursos, estos pueden
 ingresar al sistema de diferentes maneras, las cuales se mencionan en el
 capítulo~\ref{cha:conc}.}

 \item[Confiabilidad y Tolerancia a Fallas]

 La confiabilidad\index{confiabilidad} es una garantía de continuidad de los
 servicios que ofrece un sistema. Se entiende que un sistema es más proclive a
 fallas, a medida que crece su complejidad. Para poder soportar las diferentes
 garantías de servicio que ofrece, un SAD\index{SAD} deberá contar por un lado,
 con una entidad que despliegue un monitoreo\index{monitoreo} continuo de las
 capacidades del sistema y, por otro lado, de un conjunto de recursos
 redundantes a los que pueda recurrirse, cada vez que se asuma que un
 componente ha caido en falla y deba intervenirse. Sin embargo, las fallas que
 pueden presentarse en un sistema no se reducen a la caída de un componente que
 queda fuera de servicio.  En algunos casos se presentan comportamientos
 intermitentes, erráticos e, incluso, algunos tan sutiles como los que
 caracterizan a las denominadas fallas bizantinas. La especificaciones del
 diseño deberán considerar las clase de fallas que pueden tolerarse y, en
 consecuencia, los mecanismos con los que se deberá hacerles frente.

 \textit{El prototipo\index{prototipo} es en sí mismo, un espacio de
 almacenamiento confiable y autónomo\index{espacio de almacenamiento confiable
 y autónomo}, debido a la manera en que almacena los datos; dicho mecanismo se
 explica a detalle en el capítulo~\ref{cha:prototipo}.}

\end{description}

% section reqs (end)

\section{Parámetros de Desempeño}
\label{sec:desempeno}

% @TODO Aplicar las mismas "itálicas" para los parámetros de desempeño

El beneficio inmediato del almacenamiento distribuido es que se logra la
independencia entre la información y su almacén. Visto de otra forma, los
archivos que se guardan en un repositorio colectivo no dependen de un solo
dispositivo para su recuperación.  Si un archivo estuviera guardado en una sola
máquina, entonces la falla de ésta cancelaría su recuperación.  Naturalmente
que, si se guardan varias copias del mismo en otras tantas máquinas, entonces
se consigue esta independencia del almacén, pero a un costo que puede ser
excesivo. Los costos de participar en un SAD\index{SAD} se determinan a través
de sus parámetros de desempeño\index{parámetros de desempeño}. Como se ha
visto, las referencias consultadas no coinciden totalmente en las medidas que
sirven para evaluar el trabajo de estos sistemas. Hemos elegido una lista breve
de parámetros que miden la eficiencia en el uso de los recursos y la calidad de
servicio\index{calidad de servicio}~\cite{lazalde}:

\begin{description}

\item[Redundancia]

 El propósito de un sistema tolerante a fallas\index{sistema tolerante a
 fallas} es detectar y, si es posible, reparar los errores antes de que se
 manifiesten en la interfaz del usuario\index{interfaz del usuario}. La clave
 del diseño consiste en el uso de la redundancia\index{redundancia}. Este
 término se refiere a los recursos adicionales que se incluyen en el sistema,
 que no se usarían en una situación ideal. La redundancia\index{redundancia} se
 requiere para enmascarar la falla\index{falla}, luego que se detecta el error.
 Se pueden distinguir tres tipos de redundancia\index{redundancia}: de recursos
 fí­sicos, de tiempo y de información. La primera se refiere a la replicación
 de los componentes del sistema. La segunda, a la repetición de una acción de
 cómputo o de comunicaciones, sobre el dominio del tiempo. Por último, la
 redundancia\index{redundancia} de la información se refiere a una técnica de
 codificación que introduce un exceso de dígitos binarios para representar la
 información. En un sistema bien diseñado se espera conseguir la máxima
 protección contra fallas, usando la menor cantidad de recursos redundantes. 
 Entonces, la redundancia\index{redundancia} se evalúa contabilizando el
 conjunto de recursos en exceso y comparándolo con el número de fallas que con
 ello se consigue tolerar. 

\textit{ El prototipo es capaz de ofrecer dos tipos de ``niveles de servicio'',
las técnicas de ge\-ne\-ra\-ción de redundancia empleadas para cada uno de
estos niveles de servicio son la replicación simple y la codificación de los
datos utilizando el ADI (ver sección \ref{sec:almacen}, ambas técnicas ofrecen
diferentes grados de compromiso entre la redundancia generada y la
disponibilidad que ayudan a alcanzar.}

\item[Balance de carga]

Se refiere a la cantidad de información que un dispositivo recibe en resguardo,
en relación con el resto de los componentes de almacenamiento
\index{componentes de almacenamiento}. Se necesita establecer un criterio, ya
sea de equidad \index{equidad} ó de justicia \index{justicia} en función de las
características y capacidades de los nodos que participan en el sistema; de tal
forma que puedan aprovecharse los recursos disponibles de la mejor manera
posible. Porsteriormente hay que medir el cumplimiento de esta caracterí­stica.

La equidad se refiere a asignar, idealmente, la misma cantidad de información a
todos los dispositivos del conjunto; este criterio resulta adecuado en un
ambiente homogéneo. La justicia, por su parte, se refiere al hecho de asignar a
cada nodo, una cantidad de trabajo adecuada según sus capacidades; en este
caso,  componentes con mejores recursos reciben mas carga de trabajo.  En
cualquiera de las circunstancias, el balance de carga se evalúa mediante una
estadí­stica que caracteriza la cantidad de información asignada a los
dispositivos. Una medida de dispersión, como la desviación estándar, describe
el grado de cumplimiento del criterio de asignación ideal. 

% se espera que dos componentes idénticos reciban el mismo nivel de carga, pero
% se aceptan también las diferencias que pueden presentarse en un conjunto con
% capacidades heterogéneas, es decir, que los

\textit{
Partiendo del supuesto de que todos los nodos internos tienen las mismas
capacidades tanto de procesamiento y almacenamiento de datos, y que no se sabe
el tamaño de los archivos que se van a guardar en la celda, definimos en la
sección \ref{sec:almacen}, un criterio que garantiza que ninguna unidad de
datos excederá cierta cota, además se procura seleccionar el lugar en el que se
almacenará o procesará cada unidad de datos en base a un criterio que mantenga
balanceada la carga que reciben los nodos participantes; en el caso de este
prototipo, el criterio de selección consiste en acomodar a los espacios en que
se almacena la información en un círculo lógigo y empleando el mecanismo de
Round Robin para seleccionar al responsable para almacenar o procesar los
datos. Será tema de otro trabajo evaluar mecanismos alternativos de selección
con el fin de mejorar el balance de carga.}

% Ver sección \ref{sub:almacen} para la definición de UMA y EVA}.
% @TODO Hay que mejorar esta redacción

\item[Disponibilidad] 

Este parámetro tiene diferentes medidas a través de las cuales se evalúa. Puede
referirse a la probabilidad de encontrar un recurso cuando se le busca, pero
también implica el tiempo de respuesta medido desde el momento en que se
solicita el documento, hasta el momento en que se entrega al solicitante
(latencia\index{latencia}). Puede entendérsele como un indicador de la
satisfacción de los usuarios cuando invocan al sistema buscando recuperar un
contenido. Por otro lado, la calidad de servicio\index{calidad de servicio}
implica un costo asociado con los recursos donde se almacena la información y
con el ancho de banda que se requiere para su recuperación. No es lo mismo
guardar un archivo en un solo punto del sistema y transmitirlo hasta el lugar
donde se requiera, que codificarlo  y guardarlo en varios puntos. La segunda
opción implica que el documento está más disponible, pero también implica que
se han utilizado un mayor número de almacenes para soportar el mismo servicio.
Un SAD\index{SAD} debería permitir a cada usuario elegir el grado de servicio
con el que espera recuperar su información.

\textit{El parámetro de disponibilidad es atendido por nosotros empleando
técnicas de redundancia que ayuden a mejorar la probabilidad de recuperar los
contenidos almacenados en la celda aún en presencia de fallas.}
% @TODO Hay que mejorar esta redacción

\end{description}

\begin{table}
 \scriptsize
 \begin{center}
  \rowcolors{2}{LightGray}{White}
  \begin{tabular}{ p{3in} c  c  c  c }
   \textbf{Principio}         & \textbf{Redundancia} & \textbf{Balance de
   Carga} & \textbf{Disponibilidad} \\
   \toprule
   Administración dinámica y
   distribuida de metadatos      & \checkmark & \checkmark & \checkmark \\ 
   Consultas via DHT\index{DHT}             & & & \checkmark \\ 
   Control de acceso             & & \checkmark & \checkmark \\ 
   Escalabilidad                 & & \checkmark & \checkmark \\ 
   Espacios autónomos y
   confiables de almacenamiento  & \checkmark & & \checkmark \\ 
   Identificar información       & & & \checkmark \\ 
   Localización de recursos      & & \checkmark & \checkmark \\ 
   Persistencia                  & \checkmark & & \checkmark \\ 
   Preservar la consistencia     & \checkmark & & \checkmark \\ 
   Seguridad                     & \checkmark & & \checkmark \\ 
   Separación Datos - Metadatos. & \checkmark & \checkmark & \checkmark \\ 
   Simetría                      & & \checkmark & \\
   \bottomrule

  \end{tabular}
 \end{center}
 \normalsize
 \caption{Aspectos a Considerar en el Diseño de un SAD\index{SAD} vs.
 Parámetros de desempeño}
 \label{tbl:desempeno}
\end{table}

En la tabla \ref{tbl:desempeno} se observa cómo los aspectos de diseño
identificados en la sección \ref{sec:consideraciones} tienen impacto sobre los
parámetros de desempeño\index{parámetros de desempeño} que acabamos de mencionar.


\section{Dos casos de uso: almacenamiento y recuperación de archivos} % (fold)
\label{sec:doscus}

Se propone la construcción de un dispositivo virtual llamado \textbf{celda de
almacenamiento\index{celda de almacenamiento}}. Cada celda estará integrada por
un conjunto de dispositivos de almacenamiento denominados nodos internos, los
cuales son coordinados por un nodo representante\index{nodo representante}. 
Puede pensarse en cada celda\index{celda} como una red P2P\index{P2P} no
estructurada, donde el dispositivo de coordinación hace el papel de
supernodo\index{supernodo}.  Se sabe que un conjunto con estas características
puede presentar una interfaz única a través de la que ofrece capacidad
extendida y parámetros de confiabilidad mejorados~\cite{quezada}. 

\begin{figure}%[hb]
 \centering
 \includegraphics[width=0.8\textwidth]{images/celda}
 \caption{
  Celda de almacenamiento integrada por un conjunto de dispositivos bajo la
  coordinación de un representante\index{representante}.
 }
 \label{fig:celda}
\end{figure}

Se trata de un caso similar al del protocolo TCP\index{TCP}, que ofrece un
servicio con garantía de entrega y que, sin embargo, se construye partiendo del
protocolo IP\index{IP}, que no ofrece garantías (lo que se conoce como
\textit{``best effort\index{best effort}''}). La clave de este comportamiento
aparentemente paradójico se encuentra en la aplicación de recursos redundantes.
La confiabilidad\index{confiabilidad} se construye sobre la base de la
redundancia\index{redundancia} de componentes de almacenamiento y
redundancia\index{redundancia} de información. En la figura \ref{fig:celda} se
ofrece una vista panorámica de la celda de almacenamiento\index{celda de
almacenamiento}.

Por sí misma cada celda\index{celda} es un sistema de almacenamiento
distribuido\index{sistema de almacenamiento distribuido} que cubre todos los
requerimientos considerados en este capítulo.  Buscamos un diseño
flexible\index{diseño flexible}, basado en componentes de
software\index{componentes de software} que puedan implementarse en cada
dispositivo de almacenamiento\index{dispositivo de almacenamiento}, o bien,
puedan repartirse sobre nodos especializados.

\subsection{Almacenamiento de archivos} % (fold)
\label{sub:almacen}

Para hacer mas ágil la lectura del resto de este documento, hay algunos
términos que conviene definir:

\begin{description}

 \item[Unidad de datos \index{Unidad de datos}] Cualquier secuencia de bits
  encapsulada en un archivo, es decir cualquier archivo, leido en binario.

 \item[UMA\index{UMA}] Unidad Máxima de Almacenamiento\index{Unidad Máxima de
  Almacenamiento}. Es la longitud máxima permitida para almacenar una unidad de
  datos. Cualquier archivo que exceda esta medida tiene que dividirse en
  fragmentos\index{fragmentos} que cumplan con esta convención. La UMA es un
  análogo de la unidad máxima de transferencia\index{unidad máxima de
  transferencia} (MTU\index{MTU}) que se usa en las redes de conmutación de
  paquetes\index{conmutación de paquetes}. Se sabe que las solicitudes de
  atención con longitud arbitraria pueden degradar sensiblemente el desempeño
  de un sistema, dando lugar a colas de espera que crecen muy rápidamente. Se
  trata del mismo principio de la caja rápida que se usa en los supermercados.
  Es decir, un cliente puede formarse en una caja rápida, siempre que la
  cantidad de productos que va a comprar no exceda un límite. La definición de
  la UMA\index{UMA} tiene impacto sobre el balance de carga\index{balance de
  carga}, porque una unidad pequeña permite conseguir una distribución más
  homogenea de los datos. Sin embargo, también puede producir un exceso de
  carga para los procesadores  durante el almacenamiento y la recuperación que
  impacte en los tiempos de servicio.

 \item[Fragmento\index{Fragmento}] Cada una de las unidades de datos con
  longitud menor o igual a la UMA\index{UMA}, y que aún no han sido
  codificadas.

 \item[Bloque\index{Bloque}] Cada una de las unidades de datos a que da lugar
  un fragmento\index{fragmento}, luego de aplicar sobre éste replicación
  simple\index{replicación simple} o una técnica de
  codificación\index{codificación}.  En el caso de la replicación
  simple\index{replicación Simple}, un fragmento da lugar a dos bloques
  idénticos.  En el caso de ADI, cada fragmento\index{fragmento} da lugar a $n$
  bloques, también denominados dispersos.

 \item[ADI\index{ADI}] Algoritmo de dispersión de información\index{Algoritmo
  de dispersión de información} \cite{rabin}. Convierte una unidad de
  datos\index{unidad de datos} en $n$ dispersos tales que bastan cualesquiera
  $m$ de ellos para reconstruir la unidad original, con $n > m > 1$. La
  relación entre estos parámetros juega un papel muy importante en la
  definición de la cantidad de información redundante\index{información
  redundante} y la tolerancia a fallas\index{tolerancia a fallas}. Cuando $m$
  es cercana a $n$, entonces el algoritmo tolera pocas fallas, pero igualmente
  requiere poca información redundante\index{información redundante}. Cuando
  $m$ es cercana a $1$, el algoritmo soporta un mayor número de fallas, pero
  produce una cantidad muy grande de información redundante. También se tiene
  que $n$ debe ser mayor o igual a $3$. 

 \item[\textit{Checksum\index{Checksum}}] Es un mecanismo para verificar la
  integridad\index{integridad} de una unidad de datos\index{unidad de datos}. 
  Se parte de un polinomio especial $g(x)$ con coeficientes binarios,
  denominado polinomio generador\index{polinomio generador}.  Enseguida se
  genera una representación polinomial\index{representación polinomial} de la
  unidad de datos\index{unidad de datos} $m(x)$, que se multiplica por $x^r$,
  donde r es el grado de $g(x)$. El resultado se divide por $g(x)$ y se toma el
  residuo de la división $d(x)$. Se hace la suma  $m(x) * x^r + d(x)$ y se pasa
  a formato binario otra vez. Esta es la nueva unidad de datos. Puede
  entenderse como una secuencia compuesta de dos partes. La primera es idéntica
  a los datos originales, la segunda, que consta de $r$ bits, se denomina
  secuencia de verificación de integridad. Luego de que se ha almacenado o
  transmitido, se puede utilizar un proceso semejante y comparar las secuencia
  de verificación resultante con la que acompaña a los datos. Si éstas no
  coinciden se dice que los datos se han corrompido. En cuyo caso la unidad de
  datos debe desecharse.

 \item[EVA\index{EVA}] Espacio Virtual de Almacenamiento\index{Espacio Virtual
  de Almacenamiento}. Se trata de una ``caja'' ficticia, con capacidad acotada,
  a la que se asocian los bloques de datos que van a almacenarse. Cada
  disco puede contener uno o varios EVA\index{EVA}, este caso puede presentarse
  cuando se tienen discos de diferentes capacidades.

 \item[Round Robin \index{Round Robin}] Es una técnica que consiste en acomodar
  lógicamente un conjunto de recursos en una cola circular para seleccionar lo
  más equitativamente posible cada uno de ellos y mejorar el balance de carga.
  % @TODO Arreglar esto para describir la lista cirtuclar 

\end{description}

Cuando un usuario desea almacenar un archivo, se conecta a la
celda\index{celda} a través de su representante\index{representante}, el cual,
luego de registrar la operación de almacenamiento\index{almacenamiento},
delegará la responsabilidad de almacenar el archivo en uno de los nodos
internos de la celda. Cuando el nodo seleccionado reciba la orden de almacenar
un archivo, si su tamaño excede la UMA\index{UMA} definida en el sistema, lo
dividirá en tantos fragmentos\index{fragmentos} como sea necesario de tal forma
que ninguno exceda ésta medida; acto seguido, el nodo enviará cada uno de los
fragmentos resultantes a sus vecinos (y conservará algunos en caso de ser
necesario) para que sean procesados, según el nivel de servicio\index{nivel de
servicio} que se le esté otorgando al usuario (serán replicados o codificados
usando el algoritmo de dispersión de información), para generar los bloques que
finalmente se almacenarán en los espacios virtuales de
almacenamiento\index{espacios virtuales de almacenamiento} designados. Tal
intercambio de mensajes, se ilustra en la figura \ref{fig:envio}.

\begin{figure}%[ht]
 \centering
 \includegraphics[width=0.97\textwidth]{images/almacenamiento}
 \caption{Secuencia de mensajes durante el proceso de almacenamiento}
 \label{fig:envio}
\end{figure}

En el algoritmo~\ref{alg:proxy} se define la acción que realiza el
representante de la celda cuando recibe la orden de almacenar un archivo, esta
acción se ilustra en la figura~\ref{fig:envio}a.

\begin{algorithm}%[H]

 \begin{algorithmic}[1]
  \REQUIRE Una tupla de la forma: $(DB,F)$
  \ENSURE Una tupla de la forma $(estado,version)$
  \STATE $destino \leftarrow siguiente(V)$ 
  \STATE $(id, version) \leftarrow registraArchivo(DB,F)$
  \STATE $estado \leftarrow enviaArchivo(destino,F)$

  \RETURN $(estado, version)$
 \end{algorithmic}

 \caption{El representante de la celda recibe la orden de almacenar un archivo}
 \label{alg:proxy}
\end{algorithm}

En el algoritmo~\ref{alg:procarchivo} se ilustra el algoritmo que sigue un
EVA\index{EVA} para almacenar un archivo. El algoritmo recibe como entrada una
tupla de la forma $(V,S,C,A,DB,MSU)$ donde:

\begin{description}
 \item[V] Es un conjunto que contiene todos los EVA\index{EVA} que integran la
  celda de almacenamiento\index{celda de almacenamiento}.

 \item[S] Un flujo de datos\index{flujo de datos} que contiene el archivo que
  se va a almacenar.
 \item[C] Una cadena de caracteres que contiene el
  \textit{checksum\index{checksum}} del archivo que se quiere almacenar, con la
  finalidad de verificar que el archivo fue recibido correctamente.

 \item[A] Una referencia para identificar el archivo dentro del sistema.

 \item[DB] Un objeto que representa el controlador de la base de datos en donde
  se almacenan los metadatos generados durante la operación.

 \item[MSU\index{MSU}] Un número entero positivo que representa el tamaño de la
  unidad máxima de almacenamiento\index{unidad máxima de almacenamiento}.

\end{description}

\begin{algorithm}[H]

 \begin{algorithmic}[1]
  \REQUIRE Una tupla de la forma: $(V, S, C, A, DB, MSU)$ 
  \ENSURE Un valor que indica si la operación se realizó exitosamente o
  hubo algún error.
  \STATE $exito \leftarrow \TRUE$
  \IF{$C$ = getCheckSum($S$)}
   \STATE $i \leftarrow 0$
   \STATE $F \leftarrow rebana(S,MSU)$ \label{lin:rebana}
   \FOR{$f \in F$}
    \STATE $destino \leftarrow siguiente(V)$ \label{lin:siguiente}
	\STATE $checksum \leftarrow getCheckSum(f)$ \label{lin:check}
    \STATE $id \leftarrow registraFragmento(DB,f,A,i,checksum,talla(f),destino)$
	\IF{ $destino = YO()$ }
	 \STATE $procesaFragmentoLocal(f,checksum,id)$
	\ELSE
	 \STATE $conexion \leftarrow conectar(destino)$
     \STATE $procesaFragmento(f,checksum,id)$
	\ENDIF
	 \STATE $i \leftarrow i + 1$
   \ENDFOR
  \ELSE
   \STATE $exito \leftarrow \FALSE$
  \ENDIF 
  \RETURN $exito$
 \end{algorithmic}
 \caption{Procesar archivo}
 \label{alg:procarchivo}
\end{algorithm}


Para entender mejor el algoritmo~\ref{alg:procarchivo}, hay algunas líneas del
mismo que conviene explicar:

En la línea~\ref{lin:rebana} se llama a un procedimiento que simplemente divide
el flujo de datos $S$ en fragmentos de tamaño menor o igual a la unidad máxima
de almacenamiento dada por el parámetro $MSU$.

En la línea~\ref{lin:siguiente} se selecciona el siguiente EVA\index{EVA} al que
se le va a asignar que procese un fragmento\index{fragmento} de acuerdo con cierto
criterio, para el caso de este prototipo, los EVA\index{EVA} que componen la
celda, son ordenados lógicamente en una cola circular, y el EVA\index{EVA}
seleccionado es el siguiente de la lista.

En la línea~\ref{lin:check} se calcula el \textit{checksum\index{checksum}} de
cada uno de los fragmentos.

\begin{algorithm}%[H]

 \begin{algorithmic}[1]
  \REQUIRE Una tupla de la forma: $(C, F)$ 
  \ENSURE Un valor que indica si la operación se realizó exitosamente o
  hubo algún error.
  \STATE $exito \leftarrow \TRUE$
  \IF{ \NOT $C = getCheckSum(F) $ }
   \STATE $ exito \leftarrow \FALSE $
  \ELSE
   \STATE $ procesaFragmentoLocal(F, checksum)$
  \ENDIF
  \RETURN $exito$
 \end{algorithmic}
 \caption{Procesar Fragmento}
 \label{alg:procfragmento}
\end{algorithm}

% subsubsection almacen (end)

\subsection{Recuperación de archivos} % (fold)
\label{sub:recuperacion}

\begin{figure}%[ht]
 \centering
 \includegraphics[width=0.97\textwidth]{images/recuperando}
 \caption{Secuencia de mensajes durante el proceso de recuperación
 \index{recuperación}}
 \label{fig:recuperar}
\end{figure}

La operación inversa al proceso de almacenamiento\index{almacenamiento} es la
recuperación\index{recuperación}, en ella, el usuario le solicita a la celda, a
través de su representante, la entrega de un archivo. Cuando el representante
recibe la solicitud, consulta sus metadatos para saber a qué EVA\index{EVA} le
delegó la responsabilidad de almacenar el archivo, y le envía un mensaje con la
orden de recuperarlo.

Cuando el EVA\index{EVA} correspondiente recibe dicha solicitud por parte del
representante\index{representante}, busca en sus metadatos\index{metadatos}, a
quienes de sus vecinos les delegó el procesamiento de los fragmentos que generó
a partir del archivo solicitado, y en consecuencia les solicita que le
devuelvan el fragmento\index{fragmento} que procesaron.

Cuando cada uno de los EVA\index{EVA}'s que procesaron un
fragmento\index{fragmento} recibe la orden de devolverlo, revisa en sus
metadatos, que tipo de bloques generó para el fragmento\index{fragmento} que
procesó, en caso de haberlo replicado, simplemente devuelve la réplica que
almacenó, ya sea en su propio disco, o en el EVA\index{EVA} vecino. En el caso
de haber brindado el nivel de servicio ADI, el nodo consulta en sus metadatos a
quienes de sus vecinos les dio a guardar los bloques del
fragmento\index{fragmento} que es su responsabilidad de volver, recupera
algunos de ellos para regenerar el fragmento\index{fragmento}, y lo devuelve.

Cuando todos los fragmentos han sido recuperados, el EVA\index{EVA} responsable
de entregar el archivo une los fragmentos y le entrega el archivo reconstruido
al representante de la celda, quien hace lo propio al devolver el archivo al
usuario.

% subsubsection recuperacion} (end)

\section{Definiendo el espacio de almacenamiento} % (fold)
\label{sec:almacen}

% \begin{wrapfigure}{r}{0.7\textwidth}%[ht]
\begin{figure}[ht]
 \centering
 \includegraphics[width=0.99\textwidth]{images/referencia}
 \caption{Arquitectura de referencia\index{Arquitectura de referencia} tomada
 del trabajo \textit{A survey of data management in peer-to-peer systems}
  ~\cite{sung}}
 \label{fig:arqreferencia}
\end{figure}
% \end{wrapfigure}

Partiendo de las consideraciones presentadas observamos la conveniencia de
adoptar la arquitectura\index{arquitectura} de referencia propuesta en
~\cite{sung}. En dicho trabajo, los autores proponen que un sistema para manejar
datos basado en P2P\index{P2P}, necesita separar las interfaces, tanto de
comunicaciones, de usuario como los datos, del núcleo del sistema, por otro
lado en dicho núcleo, se necesitan componentes responsables de manejar las
consultas recibidas del exterior, y controlar tanto el caché, como las
actualizaciones de la información que almacenan, tal como se muestra en la
figura \ref{fig:arqreferencia}.  Los autores también proponen que, dependiendo
de la fun\-cio\-na\-li\-dad específica de un nodo, algunos de los componentes
pueden aparecer o no, o pueden combinarse para ajustarse a las necesidades del
sistema. 

A pesar de la flexibilidad\index{flexibilidad} que nos ofrece el diseño
de~\cite{sung}, la arquitectura\index{arquitectura} de referencia tiene
deficiencias considerables con respecto a los aspectos de diseño que
identificamos, por ejemplo, no considera un componente que se encargue de
monitorear y controlar el comportamiento del sistema, ni considera la
posibilidad de introducir redundancia\index{redundancia} en los datos
almacenados. Es por esto que a partir de la arquitectura\index{arquitectura} de
referencia, nos dimos a la tarea de modificarla para adaptarla a los
requerimientos que identificamos.

Luego de un proceso de análisis la arquitectura\index{arquitectura} evolucionó
hacia una segunda etapa, en la cual ya se contemplan componentes específicos
para atender aspectos tales como la redundancia\index{redundancia}, el manejo
de fallas, índices, caché y metadatos, así como las interfaces de comunicación
hacia la red, el usuario y aplicaciones externas (ver figura
\ref{fig:arqpreliminar}).

% \begin{wrapfigure}{r}{0.5\textwidth}%[ht]
\begin{figure}[hb]
 \centering
 \includegraphics[width=0.99\textwidth]{images/preliminar}
 \caption{Arquitectura preliminar\index{Arquitectura preliminar}}
 \label{fig:arqpreliminar}
\end{figure}
% \end{wrapfigure}

Aún así, la arquitectura\index{arquitectura} preliminar (mos\-tra\-da en la
figura~\ref{fig:arqpreliminar}), tiene algunas deficiencias, por ejemplo, la
interfaz de usuario no está totalmente desacoplada del núcleo del sistema. No
se considera tampoco, cómo conectar el EVA\index{EVA} con mecanismos externos
(por ejemplo el ADI), para agregar redundacia, o un mecanismo para conectarlo
con un DHT\index{DHT}, con el fin de escalar el sistema hacia una red
P2P\index{P2P} estructurada. Por todo esto, en un segundo refinamiento que
condujo a la propuesta final (ilustrada en la figura \ref{fig:arqpropuesta}).
En ella aparecen nuevos elementos entre los que destacan las interfaces para
delegar responsabilidades sobre componentes independientes e incluso externos
al sistema, como es el caso del manejo de metadatos, o de índices basados en
DHT\index{DHT}; además se hace explícito el desacoplamiento entre  la interfaz
de usuario y el núcleo del sistema, al igual que el acceso a consultas. Con
esta última decisión se espera poder atender consultas sensibles a la
semántica, o libres de semántica, a través de una interfaz de programación de
aplicaciones.

% \begin{wrapfigure}{l}{0.5\textwidth}%[ht]
\begin{figure}[hb]
 \centering
 \includegraphics[width=0.99\textwidth]{images/propuesta}
 \caption{Arquitectura propuesta\index{arquitectura propuesta}}
 \label{fig:arqpropuesta}
\end{figure}
% \end{wrapfigure}

% section almacen (end)

% section defarq (end)

% chapter propuesta (end)



